"""
股票监控服务
持续监控股票，发现买卖点时推送通知
"""
import asyncio
import logging
from datetime import datetime, date
from typing import List, Dict, Optional
from database import get_db, TradingSignal
from analysis.signal_generator import SignalGenerator
from api.stock_api import StockAPIClient

logger = logging.getLogger(__name__)

class StockMonitoringService:
    """股票监控服务"""
    
    def __init__(self):
        self.is_running = False
        self.interval_seconds = 30
        self.monitoring_task: Optional[asyncio.Task] = None
        self.registered_devices: List[str] = []
        self.monitoring_stock_count = 100
        self.last_update_time = 0
        self.start_time: Optional[datetime] = None
        
        self.signal_generator = SignalGenerator()
        self.stock_api = StockAPIClient()
        
        # 买卖信号冷却时间（避免重复推送）
        self.signal_cooldown: Dict[str, datetime] = {}
        self.cooldown_minutes = 60  # 1小时内相同股票不重复推送
        
        logger.info("📱 监控服务已初始化")
    
    async def start(self, interval_seconds: int = 30):
        """启动监控服务"""
        if self.is_running:
            logger.warning("⚠️ 监控服务已在运行中")
            return False
        
        self.interval_seconds = interval_seconds
        self.is_running = True
        self.start_time = datetime.now()
        
        logger.info(f"🚀 启动股票监控服务，间隔：{interval_seconds}秒")
        
        # 创建异步任务
        self.monitoring_task = asyncio.create_task(self._monitoring_loop())
        return True
    
    async def stop(self):
        """停止监控服务"""
        if not self.is_running:
            logger.warning("⚠️ 监控服务未运行")
            return False
        
        self.is_running = False
        
        if self.monitoring_task:
            self.monitoring_task.cancel()
            try:
                await self.monitoring_task
            except asyncio.CancelledError:
                logger.info("✅ 监控任务已取消")
        
        logger.info("⏹️ 监控服务已停止")
        return True
    
    async def _monitoring_loop(self):
        """监控循环"""
        cycle_count = 0
        
        try:
            while self.is_running:
                cycle_count += 1
                logger.info(f"🔄 执行第 {cycle_count} 轮监控...")
                
                await self._monitor_stocks()
                
                self.last_update_time = int(datetime.now().timestamp() * 1000)
                
                # 等待下一轮
                await asyncio.sleep(self.interval_seconds)
                
        except asyncio.CancelledError:
            logger.info("🛑 监控循环已取消")
            raise
        except Exception as e:
            logger.error(f"❌ 监控循环异常: {e}")
            import traceback
            logger.error(traceback.format_exc())
            self.is_running = False
    
    async def _monitor_stocks(self):
        """监控股票并发现买卖信号"""
        try:
            # 1. 查询今天已有的信号（避免重复分析）
            today = date.today()
            db = next(get_db())
            
            existing_signals = db.query(TradingSignal).filter(
                TradingSignal.signal_date == today,
                TradingSignal.signal_type.in_(['BUY', 'STRONG_BUY', 'SELL', 'STRONG_SELL'])
            ).all()
            
            # 提取已分析过的股票代码
            analyzed_symbols = {
                signal.symbol.replace('sh', '').replace('sz', ''): signal
                for signal in existing_signals
            }
            
            logger.info(f"📊 数据库中已有 {len(analyzed_symbols)} 只股票的信号")
            
            # 2. 检查是否有新的买卖信号需要推送
            buy_signals = []
            sell_signals = []
            
            for symbol, signal in analyzed_symbols.items():
                # 检查冷却时间
                if not self._can_push_signal(symbol):
                    continue
                
                if signal.signal_type in ['BUY', 'STRONG_BUY']:
                    buy_signals.append(signal)
                elif signal.signal_type in ['SELL', 'STRONG_SELL']:
                    sell_signals.append(signal)
            
            logger.info(f"🔔 本轮发现: {len(buy_signals)}个买入信号, {len(sell_signals)}个卖出信号")
            
            # 3. 推送信号
            if buy_signals or sell_signals:
                await self._push_signals(buy_signals, sell_signals)
            
            db.close()
            
        except Exception as e:
            logger.error(f"❌ 监控股票失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
    
    def _can_push_signal(self, symbol: str) -> bool:
        """检查是否可以推送信号（冷却时间检查）"""
        if symbol not in self.signal_cooldown:
            return True
        
        last_push_time = self.signal_cooldown[symbol]
        time_diff = (datetime.now() - last_push_time).total_seconds() / 60
        
        return time_diff >= self.cooldown_minutes
    
    async def _push_signals(self, buy_signals: List[TradingSignal], sell_signals: List[TradingSignal]):
        """推送买卖信号到所有设备"""
        if not self.registered_devices:
            logger.warning("⚠️ 没有注册的设备")
            return
        
        logger.info(f"📤 推送信号给 {len(self.registered_devices)} 个设备...")
        
        # 导入推送模块（避免循环导入）
        from push_service import send_buy_signal, send_sell_signal, send_batch_update
        
        pushed_count = 0
        
        # 推送买入信号
        for signal in buy_signals:
            symbol = signal.symbol.replace('sh', '').replace('sz', '')
            
            for device_token in self.registered_devices:
                try:
                    success = await send_buy_signal(
                        device_token,
                        symbol,
                        signal.symbol,  # 可能需要从数据库获取股票名称
                        signal.price,
                        signal.reason
                    )
                    
                    if success:
                        pushed_count += 1
                        # 更新冷却时间
                        self.signal_cooldown[symbol] = datetime.now()
                        
                except Exception as e:
                    logger.error(f"❌ 推送买入信号失败 ({symbol}): {e}")
        
        # 推送卖出信号
        for signal in sell_signals:
            symbol = signal.symbol.replace('sh', '').replace('sz', '')
            
            for device_token in self.registered_devices:
                try:
                    success = await send_sell_signal(
                        device_token,
                        symbol,
                        signal.symbol,
                        signal.price,
                        signal.reason
                    )
                    
                    if success:
                        pushed_count += 1
                        # 更新冷却时间
                        self.signal_cooldown[symbol] = datetime.now()
                        
                except Exception as e:
                    logger.error(f"❌ 推送卖出信号失败 ({symbol}): {e}")
        
        # 推送批量更新通知
        if buy_signals or sell_signals:
            for device_token in self.registered_devices:
                try:
                    await send_batch_update(
                        device_token,
                        len(buy_signals),
                        len(sell_signals)
                    )
                except Exception as e:
                    logger.error(f"❌ 推送批量更新失败: {e}")
        
        logger.info(f"✅ 推送完成，成功 {pushed_count} 次")
    
    def register_device(self, token: str):
        """注册设备Token"""
        if token not in self.registered_devices:
            self.registered_devices.append(token)
            logger.info(f"📱 设备已注册，当前 {len(self.registered_devices)} 个设备")
            return True
        else:
            logger.info(f"ℹ️ 设备已存在")
            return False
    
    def unregister_device(self, token: str):
        """取消注册设备"""
        if token in self.registered_devices:
            self.registered_devices.remove(token)
            logger.info(f"📱 设备已取消注册，当前 {len(self.registered_devices)} 个设备")
            return True
        return False
    
    def get_status(self) -> Dict:
        """获取监控状态"""
        return {
            "isActive": self.is_running,
            "intervalSeconds": self.interval_seconds,
            "monitoringStockCount": self.monitoring_stock_count,
            "lastUpdateTime": self.last_update_time,
            "registeredDevices": len(self.registered_devices),
            "startTime": self.start_time.isoformat() if self.start_time else None
        }

# 全局监控服务实例
monitoring_service = StockMonitoringService()

